package com.yhy.wxzn.wcs.websocket.bean;

import com.yhy.wxzn.common.utils.SpringUtil;
import com.yhy.wxzn.wcs.SystemInit;
import com.yhy.wxzn.wcs.device.plc.bean.FourCarPlc;
import com.yhy.wxzn.wcs.device.rgv.bean.Node;
import com.yhy.wxzn.wcs.device.rgv.bean.Route;
import com.yhy.wxzn.wcs.device.rgv.bean.Coord;
import com.yhy.wxzn.wcs.device.rgv.core.lock.LockNodeManager;
import com.yhy.wxzn.wcs.device.rgv.core.pathplanning.PathPlaningHandlerImpl;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeType;
import com.yhy.wxzn.wcs.device.rgv.enums.PalletStatus;
import com.yhy.wxzn.wcs.service.impl.WcsMapInfoServiceImpl;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;


@Data
public class FloorInfo {

    //小车信
    List<RgvInfo> rgvInfos;


    //输送线
    List<Station> stations;

    //已被锁的所有节点
    List<Coord> lockedCoordinate;



    @Data
    public static class RgvInfo {
        /**
         * 小车当前位置
         */
        private Coord location;
        /**
         * 小车的编号
         */
        private Integer rgvNo;
        /**
         * 小车是否载重, 详见{@link PalletStatus}
         */
        protected PalletStatus palletStatus;

        /**
         * 小车状态
         */
        protected String rgvStatus;
        /**
         * 小车行驶方向
         */
        protected String direction;

        private static List<RgvInfo> buildRgvFloorInfos(int floor){
            return SystemInit.fourWayRgvs.stream()
                    .filter(
                            rgv ->{
                                boolean res = false;
                                try {
                                    res = rgv.getCurLocation().getZ() == floor;
                                }catch (Exception e){}
                                return res;
                            }
                    )
                    .map(rgv -> {
                        RgvInfo rgvFloorInfo = new RgvInfo();
                        Coord coord = new Coord();
                        try {
                            coord = rgv.getCurLocation();
                        }catch (Exception e){}

                        rgvFloorInfo.setLocation(coord);
                        rgvFloorInfo.setRgvNo(rgv.getDeviceInfo().getId());
                        rgvFloorInfo.setPalletStatus(rgv.getFourCarPlc().getPalletStatus());
                        rgvFloorInfo.setRgvStatus(FourCarPlc.getCarStatusStr(rgv.getFourCarPlc().getCarStatus()));
                        return rgvFloorInfo;
                    }).collect(Collectors.toList());

        }



        public static List<RgvInfo> buildTestRgvFloorInfos(int floor){
            return RgvDriveInfo.getRgvInfos(floor,5);
        }


        static class RgvDriveInfo{
            static List<RgvInfo> rgvInfos = new ArrayList<>();
            static List<List<Node>> path;
            static int floor = 0;

            public static List<RgvInfo> getRgvInfos(int f,int n) {
                if (floor != f ){
                    init(f,n);
                    return rgvInfos;
                }


                List<Node> nodeByFloor = SpringUtil.getBean(WcsMapInfoServiceImpl.class).getNodeByFloor(f);
                for (int i = 0; i < n; i++) {
                    RgvInfo rgvInfo = rgvInfos.get(i);
                    Coord location = rgvInfo.getLocation();
                    List<Node> nodes = path.get(i);


                    if (location.equals(nodes.get(nodes.size() - 1))){

                        List<Route> routes = new PathPlaningHandlerImpl(nodeByFloor).calculatePath(new Node(rgvInfos.get(i).getLocation())
                                , new Node( randomPNode(f))
                                , rgvInfos.get(i).palletStatus.equals(PalletStatus.UP) ? true : false);
                        path.set(i,routes.get(0).getPath());
                        rgvInfo.setPalletStatus(randomPalletStatus());
                        rgvInfo.setRgvStatus(randomStatus());
                    }else {
                        int index = nodes.indexOf(location) + 1;
                        Coord coord2 = new Coord(nodes.get(index));
                        rgvInfo.setDirection(getDirect(rgvInfo.getLocation(),coord2));
                        rgvInfo.setLocation(coord2);
                    }
                }

                return rgvInfos;
            }

            private static String getDirect(Coord location, Coord coord2) {
                if (location.getX() > coord2.getX())
                    return "x-";
                if (location.getX() < coord2.getX())
                    return "x+";

                if (location.getY() > coord2.getY())
                    return "y-";

                return "y+";
            }

            private static void init(int f,int n) {
                floor = f;
                rgvInfos = new ArrayList<>();
                path = new ArrayList<>();
                List<Node> nodeByFloor = SpringUtil.getBean(WcsMapInfoServiceImpl.class).getNodeByFloor(f);
                for (int i = 0; i < n; i++) {
                    rgvInfos.add(initRgvInfo(f,n,i));

                    List<Route> routes = new PathPlaningHandlerImpl(nodeByFloor).calculatePath( new Node(rgvInfos.get(i).getLocation())
                            , new Node( randomPNode(f))
                            , rgvInfos.get(i).palletStatus.equals(PalletStatus.UP) ? true : false);
                    path.add(routes.get(0).getPath());
                }
            }

            private static RgvInfo initRgvInfo(int f, int n,int i) {
                RgvInfo rgvInfo = new RgvInfo();
                rgvInfo.setRgvNo(i);
                rgvInfo.setLocation(randomPNode(f));
                rgvInfo.setDirection(randomDirect());
                rgvInfo.setPalletStatus(randomPalletStatus());
                rgvInfo.setRgvStatus(randomStatus());
                return rgvInfo;
            }

            private static String randomStatus() {
                Random random = new Random();
                return random.nextInt(2) == 0 ? "正常":"异常";
            }

            private static PalletStatus randomPalletStatus() {
                Random random = new Random();
                return PalletStatus.parseStatus(random.nextInt(2));
            }

            static String[] directs = new String[]{"x+","x-","y+","y-"};
            private static String randomDirect() {
                Random random = new Random();
                return directs[random.nextInt(4)];
            }

            private static Coord randomPNode(int f) {
                List<Node> nodeByFloor = SpringUtil.getBean(WcsMapInfoServiceImpl.class).getNodeByFloor(f);
                List<Node> collect = nodeByFloor.parallelStream().filter(n -> n.getNodeType().equals(NodeType.P)).collect(Collectors.toList());
                Random random = new Random();
                return new Coord(collect.get(random.nextInt(collect.size())));
            }


        }
    }




    @Data
    public static class Station {
        /**
         * 工位上的托盘号
         */
        private String palletNo;
        /**
         * 工位是否有货
         */
        private String palletExist;
        /**
         * 工位运行状态
         */
        private String runIng;
        /**
         * 设备坐标
         */
        private Coord deviceLocation;

        private static List<Station> buildStationInfos(int floor){
            ArrayList<Station> stations = new ArrayList<>();

//            SpringUtil.getBean()
//            XjPlcDriver xjPlcDriver = new ArrayList<>(plcDriverMap.values()).get(0);
//            xjPlcDriver.plcDataPacket.getTransmissionReadPlcMap().get()

            return null;
        }
    }


    public static FloorInfo buildFloorInfo(int floor){
        FloorInfo floorInfo = new FloorInfo();
        floorInfo.setRgvInfos(RgvInfo.buildRgvFloorInfos(floor));
        floorInfo.setStations(buildTestStationInfos(floor));
        floorInfo.setLockedCoordinate(LockNodeManager.getLockedNodesByFloor(floor));
        return floorInfo;
    }


    static List<Coord> stationCoords = new ArrayList<>();
    static Set<Coord> stationCoordsSet = new HashSet<>();
    static Integer stationCoordIndex = 0;
    static {
        stationCoords.add(new Coord(14,134,1));
        stationCoords.add(new Coord(15,134,1));
        stationCoords.add(new Coord(16,134,1));
        stationCoords.add(new Coord(16,133,1));
        stationCoords.add(new Coord(16,132,1));
        stationCoords.add(new Coord(17,132,1));
        stationCoords.add(new Coord(17,133,1));
        stationCoords.add(new Coord(17,134,1));
        stationCoords.add(new Coord(16,134,1));
        stationCoords.add(new Coord(15,134,1));
        stationCoords.add(new Coord(14,134,1));
        stationCoordsSet.addAll(stationCoords);
    }
    private static List<FloorInfo.Station> buildTestStationInfos(int f) {
        ArrayList<FloorInfo.Station> res = new ArrayList<>();
        if (stationCoordIndex == stationCoords.size()) stationCoordIndex = 0;
        Coord coord = stationCoords.get(stationCoordIndex++);
        for (Coord coord1 : stationCoordsSet) {
            Station station = new Station();
            station.setDeviceLocation(coord1);
            station.setPalletExist(coord.equals(coord1) ? "存在":"不存在");
            station.setRunIng(coord.equals(coord1) ? "运行":"不运行");

            station.setPalletNo(UUID.randomUUID().toString());
            res.add(station);
        }

        return res;
    }


    private static List<Coord> buildTestLockedCoordinate() {
        ArrayList<Coord> res = new ArrayList<>();
        for (int i = 0; i < RgvInfo.RgvDriveInfo.rgvInfos.size(); i++) {
            RgvInfo rgvInfo = RgvInfo.RgvDriveInfo.rgvInfos.get(i);
            List<Node> nodes = RgvInfo.RgvDriveInfo.path.get(i);
            Coord location = rgvInfo.getLocation();
            int index = nodes.indexOf(location);
            for (int i1 = index + 1; i1 < nodes.size(); i1++) {
                if (!Node.isStraight(location,nodes.get(i1))) break;
                res.add(new Coord(nodes.get(i1)));
            }
        }

        return res;
    }


}
